package com.icloud.cer.rest.web.service;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.icloud.cer.rest.Constants;
import com.icloud.cer.rest.common.BizException;
import com.icloud.cer.rest.common.MessageCode;
import com.icloud.cer.rest.config.ServerConfigHolder;
import com.icloud.cer.rest.msg.MessageHolder;
import com.icloud.cer.rest.msg.MsgConstants;
import com.icloud.cer.rest.msg.bean.ClientView;
import com.icloud.cer.rest.msg.bean.EncryptResponse;
import com.icloud.cer.rest.msg.bean.HeartbeatResponse;
import com.icloud.cer.rest.util.ApplicationContextHelper;
import com.icloud.cer.rest.util.ConnectorManager;
import com.icloud.cer.rest.util.MessageUtils;
import com.icloud.cer.rest.util.SenderManager;
import com.icloud.cer.rest.util.SenderManager.TimeoutMessage;
import com.icloud.cer.rest.util.StringUtils;
import com.icloud.cer.rest.web.bean.CipherText;
import com.icloud.cer.rest.web.bean.EncryptResult;
import com.icloud.cer.rest.web.bean.EncryptorInfo;
import com.icloud.cer.rest.web.bean.EncryptorStatus;
import com.icloud.cer.rest.web.bean.ServerConfig;
import com.icloud.cer.rest.web.bean.ServerInfo;
import com.icloud.cer.rest.web.bean.ServerStatus;
/**
 * 
 * @author hok
 *
 */
public class EncryptServiceImpl implements EncryptService{
	private Logger log = Logger.getLogger(EncryptServiceImpl.class);
	
	public EncryptResult doEncrypt(String userId, String certification) {
		EncryptResult result = new EncryptResult();
		if(userId == null || userId.trim().length() == 0) {
			log.error("param:userId is null or empty.");
			return null;
		}
		if(certification == null || certification.trim().length() == 0) {
			log.error("param:certification is null or empty.");
			throw new BizException(MessageCode.E10012);
		}
		char[] cCer = certification.toCharArray();
		
		if(cCer.length != 256) {
			log.error("certification's length not equals 256");
			throw new BizException(MessageCode.E10012);
		}
		
		SenderManager senderManager = ApplicationContextHelper.getBean("senderManager");
		MessageHolder requestHolder = MessageUtils.getEncryptRequestHolder(userId, certification);
		long timeout = Constants.DEFALUT_TIMEOUT;
		short command = MsgConstants.CLIENT_RES_ENCRYPT;
		log.info("send encrypt task:" + userId);
		MessageHolder responseHolder = senderManager.sendEncyptRequestAndWait(requestHolder, timeout,command);

		EncryptResponse enResponse = (EncryptResponse)responseHolder.getValue();
		String responseCer = enResponse.getCertificationStr();
		log.debug("加密机返回结果：" + responseCer);
		CipherText info = new CipherText();
		if(responseCer.length() != 256) {
			log.error("response certification's length not equals 256.");
			throw new BizException(MessageCode.E10012);
		}
		info.setCertification(responseCer);
		result.setInfo(info);
		result.setErrorCode(String.valueOf(enResponse.getErrorCode()));
		String errMsg = enResponse.getErrorMsgStr();
		if(StringUtils.isNotEmpty(errMsg)) {
			log.error("error message:" + errMsg);
			result.setErrorMessage(errMsg);
		}
		return result;
	}

	public ServerStatus getServerStatus(String serverId) {
		SenderManager senderManager = ApplicationContextHelper.getBean("senderManager");
		TimeoutMessage task = senderManager.getTask();
		ServerConfigHolder serverHolder = ServerConfigHolder.getInstance();
		ServerConfig config = serverHolder.getServerConfig(serverId);
		if(config == null) {
			log.error("not found server config.");
			return null;
		}
		ServerStatus status = new ServerStatus();
		status.setErrorCode(Constants.SUCCESS);
		status.setErrorMessage(StringUtils.EMPTY);
		List<ServerInfo> info = new ArrayList<ServerInfo>();
		ServerInfo serverInfo = new ServerInfo();
		serverInfo.setServerId(serverId);
		serverInfo.setServerName(config.getName());
		if(task == null) {
			serverInfo.setServerStatus(Constants.SERVER_STATUS_IDLE);
		} else {
			serverInfo.setServerStatus(Constants.SERVER_STATUS_BUSY);
		}
		serverInfo.setEncryptorId(getEncryptorIds());
		info.add(serverInfo);
		status.setInfo(info);
		return status;
	}

	public EncryptorStatus getEncryptorStatus(String encryptorId) {
		EncryptorStatus statusObj = new EncryptorStatus();
		SenderManager senderManager = ApplicationContextHelper.getBean("senderManager");
		long timeout = Constants.DEFALUT_TIMEOUT;
		short waitCmd = MsgConstants.CLIENT_RES_HEARTBEAT;
		List<MessageHolder> responseHolder = senderManager.sendHeartbeatRequestAndWait(encryptorId, timeout,waitCmd);
		List<EncryptorInfo> infoList = new ArrayList<EncryptorInfo>();
		ConnectorManager connectManager = ApplicationContextHelper.getBean("connectorManager");
		ServerConfigHolder serverHolder = ServerConfigHolder.getInstance();
		ServerConfig config = serverHolder.getSingleServerConfig();
		if(config == null) {
			log.error("not found server config.");
			return null;
		}
		
		for(MessageHolder mh : responseHolder) {
			HeartbeatResponse hr = (HeartbeatResponse)mh.getValue();
			long sessionId = mh.getSessionId();
			ClientView cv = connectManager.getClientView(sessionId);
			int status = hr.getStatus();
			EncryptorInfo encryptorInfo = new EncryptorInfo();
			encryptorInfo.setServerId(config.getId());
			encryptorInfo.setEncryptorId(cv.getEncryptorId());
			encryptorInfo.setEncryptorName(cv.getEncryptorName());
			encryptorInfo.setEncryptorStatus(String.valueOf(status));
			infoList.add(encryptorInfo);
		}
		statusObj.setEncryptorInfo(infoList);
		statusObj.setErrorCode(Constants.SUCCESS);
		statusObj.setErrorMessage(StringUtils.EMPTY);
		return statusObj;
	}
	
	private String getEncryptorIds() {
		ConnectorManager connectManager = ApplicationContextHelper.getBean("connectorManager");
		if(connectManager.hasClient()) {
			throw new BizException(MessageCode.E10014);
		}
		List<ClientView> cvList = connectManager.getAllClient();
		if(cvList.isEmpty()) {
			return StringUtils.EMPTY;
		}
		List<String> encryptorIds = new ArrayList<String>();
		for(ClientView cv : cvList) {
			encryptorIds.add(cv.getEncryptorId());
		}
		return StringUtils.join(encryptorIds.toArray(),"_" , 0, encryptorIds.size());
	}

}
